package com.ct.application.sysuser.service.impl;

import com.ct.application.commons.vo.StatusRequest;
import com.ct.application.sysrole.service.ISysUserRolesService;
import com.ct.application.system.model.vo.AdminSystemLoginVO;
import com.ct.application.system.service.IAdminSystemUserService;
import com.ct.application.sysuser.contants.SysUserContants;
import com.ct.application.sysuser.convert.SysUserConvertModelToVO;
import com.ct.application.sysuser.model.vo.SysUserDetailVO;
import com.ct.application.sysuser.model.vo.SysUserVO;
import com.ct.application.sysuser.request.*;
import com.ct.application.sysuser.service.ISystemUserService;
import com.ct.rbac.enums.RbacResultEnum;
import com.ct.rbac.model.SysApisModel;
import com.ct.rbac.model.SysMenusModel;
import com.ct.rbac.model.SysRoleModel;
import com.ct.rbac.model.SysUserModel;
import com.ct.rbac.orm.SysUserDO;
import com.ct.rbac.repository.*;
import com.ct.redis.util.RedisUtil;
import com.ct.repository.commons.PageUtils;
import com.ct.repository.convert.CopyConvertUtils;
import com.ct.system.responsity.admin.IAdminSystemUserRepository;
import com.ct.utils.JsonUtil;
import com.ct.utils.UuidUtils;
import com.ct.utils.exception.ApiException;
import com.ct.utils.jwt.JwtUtil;
import com.ct.utils.pwd.MD5Util;
import com.ct.utils.result.DeletedEnums;
import com.ct.utils.result.StatusEnums;
import com.ct.utils.threadlocal.UserThreadLocal;
import com.ct.utils.valid.ValidatorUtil;
import com.google.code.kaptcha.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
@Slf4j
public class SystemUserServiceImpl implements ISystemUserService {

    @Resource
    private ISysUserRespontory sysUserRespontory;
    @Resource
    private ISysUserRolesRespontory sysUserRolesRespontory;
    @Resource
    private IAdminSystemUserRepository adminSystemUserRepository;
    @Resource
    private IAdminSystemUserService adminSystemUserService;
    @Resource
    private ISysMenusRespontory sysMenusRespontory;
    @Resource
    private ISysApisRespontory sysApisRespontory;
    @Resource
    private SysUserConvertModelToVO sysUserConvertModelToVO;
    @Resource
    private RedisUtil<String> redisUtil;
    @Resource
    private ISysRolesRespontory sysRolesRespontory;
    @Resource
    private ISysUserRolesService sysUserRolesService;



    /**
     * 查询用户列表分页信息
     *
     * @param sysUserSearchRequest
     * @return
     */
    @Override
    public PageUtils<SysUserDetailVO> findPage(SysUserSearchRequest sysUserSearchRequest) {
        PageUtils<SysUserModel> modelPage = sysUserRespontory.findPage(sysUserSearchRequest.getPageNo(),
                sysUserSearchRequest.getPageSize(), sysUserSearchRequest.getStatus(),
                sysUserSearchRequest.getIsDeleted(),
                sysUserSearchRequest.getKeyword());
        PageUtils<SysUserDetailVO> sysUserDetailVOPageUtils = tranferPageUtilsBo(modelPage, SysUserDetailVO.class);
        return sysUserDetailVOPageUtils;
    }

    /**
     * 查询用户列表分页信息
     *
     * @param sysUserSearchRequest
     * @return
     */
    @Override
    public PageUtils<SysUserDetailVO> findUserListBySystemId(SysUserSearchRequest sysUserSearchRequest) {
        PageUtils<SysUserModel> modelPage = sysUserRespontory.findUserListBySystemId(sysUserSearchRequest.getPageNo(),
                sysUserSearchRequest.getPageSize(), sysUserSearchRequest.getStatus(),
                sysUserSearchRequest.getIsDeleted(),
                sysUserSearchRequest.getKeyword());
        PageUtils<SysUserDetailVO> sysUserDetailVOPageUtils = tranferPageUtilsBo(modelPage, SysUserDetailVO.class);
        return sysUserDetailVOPageUtils;
    }


    /**
     * 登录逻辑开发
     *
     * @param sysUserRequest
     * @return
     */
    @Override
    public SysUserVO adminLogin(SysUserRequest sysUserRequest) {
        // 1：根据account查询用户信息是否存在，如果不存在直接返回用户不正确
        SysUserModel sysUserModel = sysUserRespontory.selectBySysUserByAccount(sysUserRequest.getAccount());
        if (Objects.isNull(sysUserModel)) {
            throw new ApiException(RbacResultEnum.ACCOUNT_EXITS);
        }
        // 判断用户是否激活
        if (sysUserModel.getStatus() != null && sysUserModel.getStatus().equals(0)) {
            throw new ApiException(RbacResultEnum.NEED_LOGIN_BEN);
        }

        // 判断用户是否删除
        if (sysUserModel.getIsDeleted() != null && sysUserModel.getIsDeleted().equals(1)) {
            throw new ApiException(RbacResultEnum.ACCOUNT_EXITS);
        }

        // 增加验证码的判断
        String redisCode = redisUtil.get(Constants.KAPTCHA_SESSION_KEY + ":" + sysUserRequest.getCodeuuid());
        if (StringUtils.isEmpty(redisCode)) {
            throw new ApiException(RbacResultEnum.CREATE_CODE_ERROR);
        }

        if (!redisCode.equalsIgnoreCase(sysUserRequest.getCode())) {
            throw new ApiException(RbacResultEnum.INPUT_CODE_ERROR);
        }

        //  如果存在，就开始比较密码是否相等, 如果不相同就抛出异常
        String slatPwd = MD5Util.md5slat(sysUserRequest.getPassword(), sysUserModel.getSlat());
        if (!slatPwd.equalsIgnoreCase(sysUserModel.getPassword())) {
            throw new ApiException(RbacResultEnum.INPUT_ACCOUNT_ERRIR);
        }

        // 3: 如果相等，就把model中用户信息，放入vo中进行返回
        SysUserVO sysUserVO = sysUserConvertModelToVO.convert(sysUserModel);

        // 根据用户ID查询绑定系统
        List<AdminSystemLoginVO> adminSystemAll = adminSystemUserService.findAdminSystemLoginAll(sysUserModel.getId());
        // 判断你查询到额系统存在与否，如果不存在说明没有绑定系统
        if (CollectionUtils.isEmpty(adminSystemAll)) {
            throw new ApiException(RbacResultEnum.SYSTEM_API_EX);
        }
        // 绑定系统
        sysUserVO.setSystemList(adminSystemAll);
        sysUserVO.setSystemId(adminSystemAll.get(0).getId());
        sysUserVO.setSyscode(adminSystemAll.get(0).getSyscode());
        sysUserVO.setSysname(adminSystemAll.get(0).getSysname());

        Map<String, String> map = JwtUtil.generateToken(sysUserModel.getAccount(),
                sysUserModel.getUsername(),
                sysUserModel.getAvatar(),
                sysUserModel.getAdmin(),
                sysUserModel.getId(),
                adminSystemAll.get(0).getId(),
                adminSystemAll.get(0).getSysname(),
                adminSystemAll.get(0).getSyscode()
        );
        // 创建token
        String token = map.get("token");
        sysUserVO.setToken(token);
        sysUserVO.setRefreshTime(map.get("refreshTime"));


        // 根据用户id查询用户对应角色信息
        List<SysRoleModel> sysRoleModels = sysRolesRespontory.findRolesByUserId(sysUserModel.getId());
        if (CollectionUtils.isEmpty(sysRoleModels)) {
            throw new ApiException(RbacResultEnum.ROLE_API_EX);
        }

        sysUserVO.setRoles(sysRoleModels);
        // 根据角色列表，取出第一个角色信息
        if (!CollectionUtils.isEmpty(sysRoleModels)) {
            // 角色对应的菜单
            Long firstRoleId = sysRoleModels.get(0).getId();
            List<SysMenusModel> sysMenusList = sysMenusRespontory.findSysMenusList(firstRoleId);
            sysUserVO.setMenus(sysMenusList);
            // 角色对应的apis
            List<SysApisModel> apisList = sysApisRespontory.findRoleApis(firstRoleId);
            sysUserVO.setPermissions(apisList);
            // 把当前角色对应的权限放入到redis，方便后续的拦截器进行控制和使用
            redisUtil.set(SysUserContants.RBAC_PERMISSION_LIST + sysUserModel.getId(), JsonUtil.obj2String(apisList), JwtUtil.EXPIRE_TIME, TimeUnit.MILLISECONDS);
        }

        // 要把token放入到redis---挤下线
        redisUtil.set(SysUserContants.LOGIN_REDIS_TOKEN_KEY + sysUserModel.getId(), token, JwtUtil.EXPIRE_TIME, TimeUnit.MILLISECONDS);
        // 立即删除缓存中的验证码
        redisUtil.del(Constants.KAPTCHA_SESSION_KEY + ":" + sysUserRequest.getCodeuuid());
        // 4: 最后测试
        return sysUserVO;
    }


    /**
     * 根据ID查询用户信息
     *
     * @param id
     * @return
     */
    @Override
    public SysUserDetailVO selectById(Long id) {
        SysUserModel sysUserModel = sysUserRespontory.selectBySysUserById(id);
        SysUserDetailVO sysUserDetailVO = sysUserConvertModelToVO.convertDetail(sysUserModel);
        List<Long> userRoleIds = sysUserRolesService.findUserRoleIds(id);
        if(!CollectionUtils.isEmpty(userRoleIds)){
            StringBuilder s = new StringBuilder();
            for (int i = 0; i < userRoleIds.size(); i++) {
                s.append(String.valueOf(userRoleIds.get(i)));
                if(i<userRoleIds.size()-1){
                    s.append(",");
                }
            }
            sysUserDetailVO.setRoleIds(s.toString());
        }
        return sysUserDetailVO;
    }

    /**
     * 账号查询
     * @param account
     * @return
     */
    @Override
    public SysUserDetailVO selectByAccount(String account){
        SysUserModel sysUserModel = sysUserRespontory.selectBySysUserByAccount(account);
        SysUserDetailVO sysUserDetailVO = sysUserConvertModelToVO.convertDetail(sysUserModel);
        return sysUserDetailVO;
    }


    /**
     * 保存用户
     *
     * @param sysUserSaveRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserDetailVO saveSystemSysUsers(SysUserSaveRequest sysUserSaveRequest) {
        SysUserDO sysUserDO = CopyConvertUtils.copyProperties(sysUserSaveRequest, SysUserDO.class);
        sysUserDO.setUuid(UuidUtils.getUuid());
        String slat = UuidUtils.getUuid();
        sysUserDO.setSlat(slat);
        sysUserDO.setIsDeleted(DeletedEnums.UN_DELETED.getCode());
        sysUserDO.setPassword(MD5Util.md5slat(sysUserDO.getPassword(),slat));
        boolean b = sysUserRespontory.saveOrUpdate(sysUserDO);
        if (b){
            SysUserDetailVO sysUserDetailVO = CopyConvertUtils.copyProperties(sysUserDO, SysUserDetailVO.class);
            // 绑定角色
            sysUserRespontory.bindRolesSysUsers(sysUserDO.getId(),sysUserSaveRequest.getRoleIds());
            // 绑定系统
            adminSystemUserRepository.bindSystemByUserId(sysUserDO.getId(),UserThreadLocal.get().getSystemId());

            return sysUserDetailVO;
        }
        return null;
    }


    /**
     * 保存用户
     *
     * @param sysUserSaveRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserDetailVO saveSysUsers(SysUserSaveRequest sysUserSaveRequest) {
        SysUserDO sysUserDO = CopyConvertUtils.copyProperties(sysUserSaveRequest, SysUserDO.class);
        sysUserDO.setUuid(UuidUtils.getUuid());
        String slat = UuidUtils.getUuid();
        sysUserDO.setSlat(slat);
        sysUserDO.setIsDeleted(DeletedEnums.UN_DELETED.getCode());
        sysUserDO.setPassword(MD5Util.md5slat(sysUserDO.getPassword(),slat));
        boolean b = sysUserRespontory.save(sysUserDO);
        if (b){
            SysUserDetailVO sysUserDetailVO = CopyConvertUtils.copyProperties(sysUserDO, SysUserDetailVO.class);
            // 绑定角色
            sysUserRespontory.bindRolesSysUsers(sysUserDO.getId(),sysUserSaveRequest.getRoleIds());
            return sysUserDetailVO;
        }
        return null;
    }

    /**
     * 修改用户信息
     *
     * @param sysUserUpdateRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserDetailVO updateSysUsers(SysUserUpdateRequest sysUserUpdateRequest) {
        SysUserDO sysUserDO = CopyConvertUtils.copyProperties(sysUserUpdateRequest, SysUserDO.class);
        boolean b = sysUserRespontory.updateById(sysUserDO);
        if (b){
            sysUserDO = sysUserRespontory.getById(sysUserUpdateRequest.getId());
            // 绑定角色
            sysUserRespontory.bindRolesSysUsers(sysUserDO.getId(),sysUserUpdateRequest.getRoleIds());
            return CopyConvertUtils.copyProperties(sysUserDO,SysUserDetailVO.class);
        }
        return null;
    }

    /**
     * 修改状态
     *
     * @param statusRequest
     * @return
     */
    @Override
    public Boolean updateStatusSysUsers(StatusRequest statusRequest) {
        if(ValidatorUtil.isNumeric(statusRequest.getValue())) {
            return sysUserRespontory.updateStatus(statusRequest.getId(), statusRequest.getField(), Integer.parseInt(statusRequest.getValue()));
        }else{
            return sysUserRespontory.updateStatusStr(statusRequest.getId(), statusRequest.getField(), statusRequest.getValue());
        }
    }

    /**
     * 修改密码
     *
     * @param sysUserPasswordRequest
     * @return
     */
    @Override
    public Boolean updatePassword(SysUserPasswordRequest sysUserPasswordRequest) {
        return sysUserRespontory.updatePassword(sysUserPasswordRequest.getId(),sysUserPasswordRequest.getPassword());
    }

    /**
     * 绑定角色
     *
     * @param sysUserBindRolesRequest
     * @return
     */
    @Override
    public Boolean bindRolesSysUsers(SysUserBindRolesRequest sysUserBindRolesRequest) {
        return sysUserRespontory.bindRolesSysUsers(sysUserBindRolesRequest.getId(),sysUserBindRolesRequest.getRolesIds());
    }

    /**
     * 根据ID删除用户信息--逻辑删除
     * @param id
     * @return
     */
    @Override
    public Boolean deleteById(Long id){
        boolean b1 = adminSystemUserRepository.countUserId(id);
        if(b1){
            throw new ApiException(RbacResultEnum.SYSTEM_YINYONG_API_EX);
        }

        Boolean b = sysUserRolesRespontory.countBindUserRole(id);
        if(b){
            throw new ApiException(RbacResultEnum.USER_YINYONG_API_EX);
        }
        SysUserDO sysUserDO = new SysUserDO();
        sysUserDO.setId(id);
        sysUserDO.setIsDeleted(DeletedEnums.DELETED.getCode());
        return sysUserRespontory.updateById(sysUserDO);
    }

    /**
     * 恢复删除
     * @param id
     * @return
     */
    @Override
    public Boolean recoverById(Long id){
        SysUserDO sysUserDO = new SysUserDO();
        sysUserDO.setId(id);
        sysUserDO.setIsDeleted(DeletedEnums.UN_DELETED.getCode());
        return sysUserRespontory.updateById(sysUserDO);
    }

    /**
     * 彻底删除--物理删除
     * @param id
     * @return
     */
    @Override
    public Boolean removeById(Long id){
        Boolean b = sysUserRolesRespontory.countBindUserRole(id);
        if(b){
            throw new ApiException(RbacResultEnum.USER_YINYONG_API_EX);
        }
        return sysUserRespontory.removeById(id);
    }


    /**
     * 批量删除--物理删除
     * @param sysUserBatchRequest
     * @return
     */
    public Boolean batchRemoves(SysUserBatchRequest sysUserBatchRequest){
        // ? 如何优化处理
        return sysUserRespontory.removeBatchByIds(sysUserBatchRequest.getIds());
    }

    /**
     * 批量删除-逻辑删除
     * @param sysUserBatchRequest
     * @return
     */
    public Boolean batchDels(SysUserBatchRequest sysUserBatchRequest){
        List<Long> userIds = sysUserBatchRequest.getIds();
        List<SysUserDO> sysUserDOS = userIds.stream().map(userId -> {
            SysUserDO sysUserDO = new SysUserDO();
            sysUserDO.setId(userId);
            sysUserDO.setIsDeleted(DeletedEnums.DELETED.getCode());
            return sysUserDO;
        }).collect(Collectors.toList());
        return sysUserRespontory.updateBatchById(sysUserDOS);
    }

    /**
     * 批量恢复
     * @param sysUserBatchRequest
     * @return
     */
    public   Boolean batchRecovers(SysUserBatchRequest sysUserBatchRequest){
        List<Long> userIds = sysUserBatchRequest.getIds();
        List<SysUserDO> sysUserDOS = userIds.stream().map(userId -> {
            SysUserDO sysUserDO = new SysUserDO();
            sysUserDO.setId(userId);
            sysUserDO.setIsDeleted(DeletedEnums.UN_DELETED.getCode());
            return sysUserDO;
        }).collect(Collectors.toList());
        return sysUserRespontory.updateBatchById(sysUserDOS);
    }

    /**
     * 批量恢复
     * @param sysUserBatchRequest
     * @return
     */
    public  Boolean batchStatus(SysUserBatchRequest sysUserBatchRequest){
        List<Long> userIds = sysUserBatchRequest.getIds();
        List<SysUserDO> sysUserDOS = userIds.stream().map(userId -> {
            SysUserDO sysUserDO = new SysUserDO();
            sysUserDO.setId(userId);
            sysUserDO.setStatus(StatusEnums.STATUS.getCode());
            return sysUserDO;
        }).collect(Collectors.toList());
        return sysUserRespontory.updateBatchById(sysUserDOS);
    }

    /**
     * 批量禁止
     * @param sysUserBatchRequest
     * @return
     */
    public Boolean batchForbiddens(SysUserBatchRequest sysUserBatchRequest){
        List<Long> userIds = sysUserBatchRequest.getIds();
        List<SysUserDO> sysUserDOS = userIds.stream().map(userId -> {
            SysUserDO sysUserDO = new SysUserDO();
            sysUserDO.setId(userId);
            sysUserDO.setStatus(StatusEnums.UN_STATUS.getCode());
            return sysUserDO;
        }).collect(Collectors.toList());
        return sysUserRespontory.updateBatchById(sysUserDOS);
    }


}
